/*
 * Project name:
     EasyPIC Slalom
 * Author:
     Samuel.B.Atlan@gmail.com
 * Revision History:
     2010/04/24: initial release;
     2010/05/06: use interrupt of TIMER1 to check RE0
 * Description:
     Turns on/off LEDs with a slalom effect.
     Pressing RE0 will change the spiral direction.
 * Test configuration:
     MCU:             PIC16F887
     Dev.Board:       EasyPIC6
     Oscillator:      MCU 8.00 MHz, Internal RC no Clock (RA6 & RA7 as I/O)
     Ext. Modules:    -
     Software:        mikroC PRO for PIC 3.2
 * Notes:
     -  still have one led behaving false when changing direction. This should
        be corrected by calling tableconvert with direction=0 before changing
        again to direction = -direction.
*/

const unsigned long waiting = 50;
bit oldstate;
char i;
char chemin[32] = {1,2,3,4,5,6,7,8,16,15,14,13,12,11,10,9,17,18,19,20,21,22,23,24,32,31,30,29,28,27,26,25};
signed char direction;

void clear_PORTs() {
  PORTA = 0x00;
  PORTB = 0x00;
  PORTC = 0x00;
  PORTD = 0x00;
}
void init() {
  ANSEL  = 0;                                    // Configure AN pins as digital
  ANSELH = 0;
  C1ON_bit = 0;                                  // Disable comparators
  C2ON_bit = 0;

  TRISA = 0x00;                                  // set direction to be output
  TRISB = 0x00;                                  // set direction to be output
  TRISC = 0x00;                                  // set direction to be output
  TRISD = 0x00;                                  // set direction to be output
  TRISE0_bit = 1;                                // set RE0 pin as input

  clear_PORTs();

  T1CON = 1;                                     // Timer1 settings
  TMR1IF_bit = 0;                                // Clear TMR1IF
  TMR1H = 0x85;
  TMR1L = 0xEE;                                  // TRM1 = 34286
  TMR1IE_bit = 1;                                // Enable Timer1 interrupt
  INTCON = 0xC0;                                 // Set GIE, PEIE
}
void tableconvert(char pos) {
  if (pos>24)      { PORTD ^= 0x1 << ((pos-24) - 1); }
  else if (pos>16) { PORTC ^= 0x1 << ((pos-16) - 1); }
  else if (pos>8)  { PORTB ^= 0x1 << ((pos-8) - 1);  }
  else             { PORTA ^= 0x1 << ((pos-0) - 1);  }
}
void next(signed char direction) {
  i = i + direction;
  if (i== 0) i = 32;
  if (i==33) i = 1;
  tableconvert(chemin[i-1]);
}
void interrupt() { // invert direction of the ZigZag()
  if(TMR1IF_bit == 1) {                            //look at the overflow bit
    TMR1IF_bit = 0;
    if (Button(&PORTE, 0, 1, 1)) {                // Detect logical one (button is pushed)
      oldstate = 1;                               // Update flag
    }
    if (oldstate && Button(&PORTE, 0, 1, 0)) {    // Detect one-to-zero transition (button is released)
      direction = -direction;                     // change direction
      oldstate = 0;                               // Update flag
    }
  }
}
void main() {
  init();
  i = 0;                                          // table position counter
  direction = 1;
  oldstate = 0;
  while (1) {
    next(direction);                              // update next position with current direction
    Delay_ms(waiting);                            // wait a little bit
  }
}
